#pragma once

#include "visitor.h"

namespace zoo
{
    enum E_Animal
    {
        E_Animal_Null,
        E_Animal_Dog,
        E_Animal_Bird,
        E_Animal_Fish,
    };

    struct animal
    {
        virtual ~animal() = default;
        virtual E_Animal type() const = 0;
        virtual int move() = 0;
        virtual void accept(const visitor_token*) = 0;
        virtual void accept(const visitor_token*, int) = 0;
    };

    //CRTP
    template<class T>
    struct animal_crtp : public animal
    {
        void accept(const visitor_token* vt) override
        {
            if (const auto* p = dynamic_cast<const visitor<T>*>(vt); p)
            {
                p->visit(static_cast<T*>(this));
            }
        }

        void accept(const visitor_token* vt, int i) override
        {
            if (const auto* p = dynamic_cast<const visitor<T>*>(vt); p)
            {
                p->visit(static_cast<T*>(this), i);
            }
        }
    };
}; // !namespace zoo
